#include "kstdio.h"
#include "kmm.h"
#include "dbgio.h"
typedef struct kpipe{
	uint8_t *buffer;
	uint32_t inptr;
	uint32_t outptr;
	uint32_t bufsize;
	uint8_t mutex;
} kpipe_t;

uint32_t pipe_read(struct vfs_node *node ,uint8_t *buffer ,uint32_t offset ,uint32_t length,uint32_t fflags){
	kpipe_t *pipe = (kpipe_t *) node->inode;
	//dprintf("enter read\n");
	if((pipe->inptr + length) > pipe->bufsize)
		length = pipe->bufsize - pipe->inptr;
	while((pipe->inptr + length) > pipe->outptr) for (int sleeptmr=0;sleeptmr < 1000;sleeptmr++) __asm{nop};//SLEEP HERE
	pipe->mutex = 1;
	memcpy(buffer,pipe->buffer + pipe->inptr,length);
	pipe->inptr+=length;
	if (pipe->inptr == pipe->outptr){
		pipe->inptr = 0;
		pipe->outptr = 0;
	}
	pipe->mutex = 0;
	//dprintf("exit read\n");
	return length;
}

uint32_t pipe_write(struct vfs_node *node ,uint8_t *buffer ,uint32_t offset ,uint32_t length,uint32_t fflags){
	kpipe_t *pipe = (kpipe_t *) node->inode;
	//dprintf("Writing to pipe INB:0x%x OUTB:0x%x LEN:0x%x\n",pipe->inptr,pipe->outptr,length);
	if((pipe->outptr + length) > pipe->bufsize)
		length = pipe->bufsize - pipe->outptr;
	while(pipe->mutex);//SLEEP HERE
	memcpy(pipe->buffer + pipe->outptr,buffer,length);
	pipe->outptr+=length;
	return length;
}

int pipe_available(KFILE fd){
	process_info_t *p = get_current_process();
	fileinfo_t *file;
	ILLIST *fd_backend;
	int read = -1;
	fd_backend = illist_get(p->fd_table->fd_table,(int)fd);
	if (fd_backend == 0){
		p->errno = EBADF;
		return -1;
	}
	file = (fileinfo_t *) fd_backend->value;
	kpipe_t *pipe = (kpipe_t *) file->node->inode;
	return pipe->outptr - pipe->inptr;
}

KFILE create_loop(int bufsize){
	KFILE pipe = getfreefd();
	kpipe_t *pipet = (kpipe_t *) kmalloc(sizeof(kpipe_t));
	pipet->buffer = (uint8_t *) kmalloc(bufsize);
	pipet->bufsize = bufsize;
	pipet->inptr = 0;
	pipet->outptr = 0;
	pipet->mutex=0;
	create_fd(pipe,FREAD | FWRITE,(uint32_t) pipet,pipe_read ,pipe_write);
	return pipe;
}

KFILE *create_pipe(int bufsize){//TODO:MAKE SAFE
	KFILE *pipes = (KFILE *)kmalloc(sizeof(KFILE) * 2);
	pipes[0] = getfreefd();
	pipes[1] = getfreefd();
	kpipe_t *pipet = (kpipe_t *) kmalloc(sizeof(kpipe_t));
	pipet->buffer = (uint8_t *) kmalloc(bufsize);
	create_fd(pipes[0] ,FWRITE ,(uint32_t) pipet ,0 ,pipe_write);
	create_fd(pipes[1] ,FREAD  ,(uint32_t) pipet ,pipe_read ,0 );
	return pipes;
}